package com.nervenets.web.controller.news;

import com.nervenets.web.controller.BaseController;
import com.nervenets.web.controller.IdParams;
import com.nervenets.web.controller.IdTokenParams;
import com.nervenets.web.entity.KeyValue;
import com.nervenets.web.entity.MessageCode;
import com.nervenets.web.entity.ResponseResult;
import com.nervenets.web.hibernate.dao.NewsDao;
import com.nervenets.web.hibernate.domain.news.News;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import javax.validation.ConstraintViolation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Api(value = "资讯接口v1", description = "资讯相关接口")
@RestController
@RequestMapping("/api/v1/news")
public class NewsController extends BaseController {
    @Resource
    private NewsDao newsDao;

    @ApiOperation(value = "新建或修改资讯", response = News.class)
    @PostMapping("/edit")
    public ResponseResult edit(@RequestBody NewsEditParams params) {
        final Set<ConstraintViolation<NewsEditParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        News news = new News();
        if (params.getNewsId() > 0) {
            news = newsDao.findById(params.getNewsId()).orElse(null);
            if (null == news) return errorMessage(MessageCode.code_404, "您修改的资讯不存在");
        }

        news.setType(params.getType());
        news.setManagerId(params.getManagerId());
        news.setTitle(params.getTitle());
        news.setContent(params.getContent());

        newsDao.save(news);

        return successMessage(news);
    }

    @ApiOperation(value = "资讯列表", response = NewsModel.class)
    @PostMapping("/list")
    public ResponseResult list(@RequestBody NewsPagingParams params) {
        final Set<ConstraintViolation<NewsPagingParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        Specification<News> spec = (Specification<News>) (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(criteriaBuilder.equal(root.get("removed"), 0));

            if (params.getManagerId() > 0) {
                predicates.add(criteriaBuilder.equal(root.get("managerId"), params.getManagerId()));
            }

            if (null != params.getType()) {
                predicates.add(criteriaBuilder.equal(root.get("type"), params.getType()));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        Page<News> page = newsDao.findAll(spec, PageRequest.of(params.getPage(), params.getLimit(), new Sort(Sort.Direction.DESC, "id")));
        List<NewsModel> list = new ArrayList<>();
        page.map(news -> {
            list.add(new NewsModel(news));
            return news;
        });
        return successMessage(list, new KeyValue("page", params.getPage()), new KeyValue("total", page.getTotalElements()));
    }

    @ApiOperation(value = "资讯详情", response = News.class)
    @PostMapping("/detail")
    public ResponseResult detail(@RequestBody IdParams params) {
        final Set<ConstraintViolation<IdParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        News news = newsDao.findById(params.getTargetId()).orElse(null);
        if (null == news) return errorMessage(MessageCode.code_404, "您要查看的资讯不存在");
        return successMessage(news);
    }

    @ApiOperation(value = "资讯类型详情(针对单条资讯查询，若没有编辑，data返回false)", response = News.class)
    @PostMapping("/type")
    public ResponseResult type(@RequestBody TypeNewsParams params) {
        final Set<ConstraintViolation<TypeNewsParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        final List<News> allNews = newsDao.findAllByManagerIdAndType(params.getManagerId(), params.getType());
        if (null == allNews || allNews.isEmpty()) return successMessage(false);
        return successMessage(allNews.get(0));
    }

    @ApiOperation("删除资讯")
    @PostMapping("/delete")
    public ResponseResult delete(@RequestBody IdTokenParams params) {
        final Set<ConstraintViolation<IdTokenParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        News news = newsDao.findById(params.getTargetId()).orElse(null);
        if (null == news) return errorMessage(MessageCode.code_404, "您要删除的资讯不存在");
        newsDao.delete(news);
        return successMessage();
    }
}
